/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package jnetmonitor.ui;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Vector;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ListSelectionEvent;
import jnetmonitor.models.InterfaceComboBoxModel;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JToggleButton;
import javax.swing.ListSelectionModel;
import javax.swing.event.ChangeListener;
import javax.swing.event.ListSelectionListener;
import jnetmonitor.Util;
import jnetmonitor.entities.SniffedPacketEntity;
import jnetmonitor.models.SnifferTableModel;
import jpcap.JpcapCaptor;
import jpcap.NetworkInterface;
import jpcap.PacketReceiver;
import jpcap.packet.ARPPacket;
import jpcap.packet.EthernetPacket;
import jpcap.packet.ICMPPacket;
import jpcap.packet.IPPacket;
import jpcap.packet.Packet;

/**
 *
 * @author r1nlx0
 */
public class SnifferPanel extends JPanel {

    //private Vector<SniffedPacketEntity> sniffedDatas;
    private SnifferTableModel snifferTableModel;
    private ArrayList<NetworkInterface> availableInterfaces;
    private JComboBox interfaceComboBox;
    private JTable resultTable;
    private JToggleButton startButton;
    private JpcapCaptor capturer;
    private Vector<Packet> capturedPackets;

    public SnifferPanel() {
        initComponents();

    }

    private void initComponents() {

        availableInterfaces = new ArrayList<NetworkInterface>();
        startButton = new JToggleButton();
        snifferTableModel = new SnifferTableModel();
        //sniffedDatas = new Vector<SniffedPacketEntity>();
        JLabel jLabel1 = new javax.swing.JLabel();
        interfaceComboBox = new javax.swing.JComboBox();
        JScrollPane jScrollPane1 = new javax.swing.JScrollPane();
        resultTable = new javax.swing.JTable();
        capturedPackets = new Vector<Packet>();

        startButton.setText("Start");

        jLabel1.setText("Interfaces");

        try {
            Util.refreshInterfaces(availableInterfaces);

            InterfaceComboBoxModel interfaceComboBoxModel = new InterfaceComboBoxModel(availableInterfaces);
            interfaceComboBox.setModel(interfaceComboBoxModel);
            capturer = JpcapCaptor.openDevice(availableInterfaces.get(interfaceComboBox.getSelectedIndex()), 64 * 1024, true, 10000);
        } catch (Exception e) {
            JOptionPane.showMessageDialog(this, "Error No Interface found.\n"
                    + "Make sure at least 1 interface is up!",
                    "Error : No Interface", JOptionPane.ERROR_MESSAGE);
            interfaceComboBox.setModel(new DefaultComboBoxModel(new Object[]{"no devices"}));
        }
        
        resultTable.setModel(snifferTableModel);
        resultTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        resultTable.addMouseListener(new MouseAdapter() {

            @Override
            public void mouseClicked(MouseEvent e) {
                if(e.getClickCount() == 2){
//                System.out.print(e.getSource());
                    // ToDo detail dialog..
                    JOptionPane.showMessageDialog(SnifferPanel.this,
                        "Data :\n\n" + new String(capturedPackets.get(resultTable.getSelectedRow()).data));
                    
                }
            }
        });

        jScrollPane1.setViewportView(resultTable);

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
        this.setLayout(layout);
        layout.setHorizontalGroup(
                layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING).addGroup(layout.createSequentialGroup().addContainerGap().addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING).addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 376, Short.MAX_VALUE).addGroup(layout.createSequentialGroup().addComponent(jLabel1).addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED).addComponent(interfaceComboBox, 0, 225, Short.MAX_VALUE).addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED).addComponent(startButton))).addContainerGap()));
        layout.setVerticalGroup(
                layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING).addGroup(layout.createSequentialGroup().addContainerGap().addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE).addComponent(startButton).addComponent(interfaceComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE).addComponent(jLabel1, javax.swing.GroupLayout.PREFERRED_SIZE, 15, javax.swing.GroupLayout.PREFERRED_SIZE)).addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED).addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 275, Short.MAX_VALUE).addContainerGap()));
        interfaceComboBox.addItemListener(new ItemListener() {

            @Override
            public void itemStateChanged(ItemEvent e) {
                if (e.getStateChange() == ItemEvent.SELECTED) {
                    //System.out.println(e.getItem() + " " + capturer.getErrorMessage());
                    //System.out.println(availableInterfaces.get(interfaceComboBox.getSelectedIndex()).name);
                    try {


                        capturer = JpcapCaptor.openDevice(availableInterfaces.get(interfaceComboBox.getSelectedIndex()), 64 * 1024, true, 10000);
                        //if(capturer == null)

                        //System.out.println("Capturer  : " + capturer.getErrorMessage());
                    } catch (IOException ex) {
                        JOptionPane.showMessageDialog(SnifferPanel.this,
                                "Cannot open interface! : \n"
                                + ex.getMessage(), "Error",
                                JOptionPane.ERROR_MESSAGE);
                        Logger.getLogger(SnifferPanel.class.getName()).log(Level.SEVERE, null, ex);
                    }
                }


            }
        });

        startButton.addItemListener(new ItemListener() {

            class OnStartThread extends Thread {

                private boolean isStop = false;

                public void run() {

                    while (!isStop) {

                        System.out.println("Hello world!");
                        if (capturer == null) {
                            System.out.println("Error!");
                        }
                        capturer.loopPacket(1, new PacketReceiver() {

                            @Override
                            public void receivePacket(Packet packet) {
                                EthernetPacket ethPac = (EthernetPacket) packet.datalink;
                                snifferTableModel.addEntity(new SniffedPacketEntity(
                                        ethPac.getSourceAddress(),
                                        ethPac.getDestinationAddress(),
                                        packet.getClass().getName(),
                                        new String(packet.data)));
                                capturedPackets.add(packet);
                                //System.out.println("Packet : " +  packet.getClass().getName() );
                            }
                        });
                    }
                }

                public void requestStop() {
                    this.isStop = true;
                }
            }
            private OnStartThread onStart = null;

            @Override
            public void itemStateChanged(ItemEvent e) {

                if (e.getStateChange() == ItemEvent.SELECTED) {
                    startButton.setText("Stop");

                    onStart = new OnStartThread();
                    onStart.start();
                    interfaceComboBox.setEnabled(false);
                } else if (e.getStateChange() == ItemEvent.DESELECTED) {
                    startButton.setText("Start");
                    onStart.requestStop();
                    capturer.breakLoop();

                    interfaceComboBox.setEnabled(true);
                }
            }
        });
    }
}
